package com.liveinstars.post.business.service.impl;

import com.liveinstars.api.dto.BatchGetUserReq;
import com.liveinstars.api.dto.GetUserInfo;
import com.liveinstars.api.facade.ImUserCentreApi;
import com.liveinstars.api.im.ChatGroupApiService;
import com.liveinstars.post.business.model.entity.*;
import com.liveinstars.post.business.model.vo.PostDetailVO;
import com.liveinstars.post.business.model.vo.PostListVO;
import com.liveinstars.post.business.model.vo.SheetListVO;
import com.liveinstars.post.business.repository.PostCollectRepository;
import com.liveinstars.post.business.repository.PostLikeRepository;
import com.onepiece.cache.service.CacheService;
import com.onepiece.shipelves.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.geo.Distance;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import com.liveinstars.post.business.event.logger.LogEvent;
import com.liveinstars.post.business.exception.NotFoundException;
import com.liveinstars.post.business.model.dto.post.BasePostMinimalDTO;
import com.liveinstars.post.business.model.enums.LogType;
import com.liveinstars.post.business.model.enums.PostStatus;
import com.liveinstars.post.business.repository.ReportRepository;
import com.liveinstars.post.business.service.*;
import com.liveinstars.post.business.utils.MarkdownUtils;
import com.liveinstars.post.business.utils.ServiceUtils;

import java.util.*;
import java.util.stream.Collectors;


/**
 * Report service implementation.
 *
 * @author johnniang
 * @author ryanwang
 * @author evanwang
 * @date 2019-04-24
 */
@Slf4j
@Service
public class ReportServiceImpl extends BasePostServiceImpl<Report> implements ReportService {

    private final ReportRepository reportRepository;

    private final PostLikeRepository postLikeRepository;

    private final ApplicationEventPublisher eventPublisher;


    private ImUserCentreApi imUserCentreApi;
    public ReportServiceImpl(ReportRepository reportRepository,
                            ApplicationEventPublisher eventPublisher,
                            PostCollectRepository collectRepository,
                            PostLikeRepository likeRepository,
                            OptionService optionService,
                            ImUserCentreApi userCentreApi,
                            CacheService cacheService,
                            ChatGroupApiService chatGroupApiService) {
        super(reportRepository, collectRepository, likeRepository, optionService, cacheService, chatGroupApiService);
        this.reportRepository = reportRepository;
        this.postLikeRepository = likeRepository;
        this.eventPublisher = eventPublisher;
        this.imUserCentreApi = userCentreApi;
    }


    @Override
    public Report createBy(Report report, boolean autoSave) {
        Report createdReport = createOrUpdateBy(report);
        if (!autoSave) {
            // Log the creation
            LogEvent logEvent = new LogEvent(this, createdReport.getId().toString(), LogType.SHEET_PUBLISHED, createdReport.getTitle());
            eventPublisher.publishEvent(logEvent);
        }
        return createdReport;
    }

    @Override
    public Page<PostListVO> convertToListVo(Page<Report> reportPage) {
        Assert.notNull(reportPage, "Post page must not be null");

        List<Report> posts = reportPage.getContent();

        List<Integer> userIds = ServiceUtils.fetchPropertyList(posts, Report::getUserId);

        Map<Integer, GetUserInfo> userInfoMap = getGetUserInfoMap(userIds);

        return reportPage.map(post -> {
            PostListVO postListVO = new PostListVO().convertFrom(post);

            if (StringUtils.isBlank(postListVO.getSummary())) {
                postListVO.setSummary(generateSummary(post.getFormatContent()));
            }


            GetUserInfo getUserInfo = userInfoMap.get(post.getUserId());
            if(getUserInfo != null){
                postListVO.setUserName(getUserInfo.getUserName());
                postListVO.setUserLogo(getUserInfo.getLogo());
            }

            return postListVO;
        });
    }

    @Override
    public Page<PostListVO> convertToListVo(Page<Report> reportPage, Integer userId) {
        Assert.notNull(reportPage, "Post page must not be null");

        List<Report> posts = reportPage.getContent();

        List<Integer> userIds = ServiceUtils.fetchPropertyList(posts, Report::getUserId);

        Map<Integer, GetUserInfo> userInfoMap = getGetUserInfoMap(userIds);

        return reportPage.map(post -> {
            PostListVO postListVO = new PostListVO().convertFrom(post);

            if (StringUtils.isBlank(postListVO.getSummary())) {
                postListVO.setSummary(generateSummary(post.getFormatContent()));
            }


            GetUserInfo getUserInfo = userInfoMap.get(post.getUserId());
            if(getUserInfo != null){
                postListVO.setUserName(getUserInfo.getUserName());
                postListVO.setUserLogo(getUserInfo.getLogo());
            }

            return postListVO;
        });
    }

    @Override
    public PostDetailVO convertToDetailVoByUserId(Report report, Integer userId) {
        // Convert to detail vo
        return convertTo(report, userId);
    }

    @NonNull
    private PostDetailVO convertTo(@NonNull Report post, Integer userId) {
        Assert.notNull(post, "Post must not be null");

        // Convert to base detail vo
        PostDetailVO postDetailVO = new PostDetailVO().convertFrom(post);

        if (StringUtils.isBlank(postDetailVO.getSummary())) {
            postDetailVO.setSummary(generateSummary(post.getFormatContent()));
        }


        Result<GetUserInfo> userInfoResult = imUserCentreApi.getUserInfo(post.getUserId());
        if (userInfoResult.getCode().equals(Result.SUCCESS)) {
            postDetailVO.setUserName(userInfoResult.getData().getUserName());
            postDetailVO.setUserLogo(userInfoResult.getData().getLogo());
        }

        return postDetailVO;
    }


    @org.jetbrains.annotations.NotNull
    private Map<Integer, GetUserInfo> getGetUserInfoMap(List<Integer> userIds) {
        Map<Integer, GetUserInfo> userInfoMap = new HashMap<>();
        BatchGetUserReq batchGetUserReq = new BatchGetUserReq();
        batchGetUserReq.setUids(userIds);
        Result<List<GetUserInfo>> userInfoListResult = imUserCentreApi.batchGetUserInfo(batchGetUserReq);
        if (userInfoListResult.getCode().equals(Result.SUCCESS)) {
            List<GetUserInfo> userInfoList = userInfoListResult.getData();
            userInfoMap = ServiceUtils.convertToMap(userInfoList, GetUserInfo::getUid);
        } else {
            throw new RuntimeException(userInfoListResult.getMessage());
        }
        return userInfoMap;
    }
}
